// 模拟任务的使用
#pragma once
#include <string>
#include "log.hpp"

extern Log lg;

const size_t msg_size = 4096;

class task
{
public:
    task(int sockfd, const std::string client_ip, const uint16_t client_port)
        : _sockfd(sockfd), _client_ip(client_ip), _client_port(client_port)
    {
    }
    // 任务运行，将长任务转换为短任务
    void operator()()
    {
        char message[msg_size];

        // 由于accept返回的是一个文件描述符，所以可以利用文件操作接口来进行读取信息
        ssize_t n = read(_sockfd, message, sizeof message - 1);
        if (n > 0)
        {
            // 在传输过程中并没有将字符串结尾的'\0'也一起传输
            message[n] = '\0';
            std::string response = "serve echo# ";
            response += message;
            // 如果在服务器发送给客户端的时候app关闭，会导致OS向服务器进程发送SIGPIPE信号，会导致进程中断
            // 服务器不应该中断，所以应该对该信号忽略
            n = write(_sockfd, response.c_str(), response.size());
            if (n < 0)
            {
                lg(Warning, "write to [%s:%d] error, errno:%s, errstr:%d", _client_ip.c_str(),
                   _client_port, errno, strerror(errno));
            }
        }
        else if (n == 0)
            // 当客户端关闭时，read不会继续阻塞，并且返回0
            lg(Info, "%s client disconnect", _client_ip.c_str());
        else if (n < 0)
        {
            lg(Warning, "client read error, errno:%d, errstr:%s", errno, strerror(errno));
            errno = 0;
        }
        // 处理完任务之后需要关闭连接
        close(_sockfd);
    }

private:
    int _sockfd;
    const std::string _client_ip;
    const uint16_t _client_port;
};